package com.simple.core;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.simple.annotation.Instance;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

@Slf4j
@Instance
public class Center {
    /**
     * 观察者的管理对象
     */
    private volatile Map<String, List<Receiver>> receivers;

    public Center() {
        receivers = new HashMap<>();
    }

    /**
     * 将观察者注册到事件中心
     *
     * @param receiver 被注册的观察者
     */
    public void register(Receiver receiver) {
        List<String> actions = receiver.getActions();
        for (String action : actions) {
            List<Receiver> list = receivers.computeIfAbsent(action, k -> new ArrayList<>());
            if (CollUtil.contains(list, receiver)) {
                continue;
            }
            list.add(receiver);
        }
    }

    /**
     * 从注册中心中，注销观察者
     *
     * @param action   观察的动作，为null或者为空字符串时，将会从观察者中获取注册的动作，否则将会直接使用此动作作为观察事件
     * @param receiver 被注册的观察者
     */
    public void unregister(String action, Receiver receiver) {
        if (StrUtil.isEmpty(action)) {
            receivers.forEach((s, receivers1) -> receivers1.removeIf(receiver1 -> Objects.equals(receiver1, receiver)));
        } else {
            List<Receiver> list = receivers.get(action);
            list.remove(receiver);
        }
    }

    /**
     * 通知观察者，处理事件
     *
     * @param carrier 事件中被传递的数据
     * @param <T>     处理结果的类型
     * @return 返回观察者处理后的结果，允许单词简单的通信
     */
    public <T> List<T> notifyReceiver(Carrier carrier) {
        String action = carrier.getAction();
        List<Receiver> list = receivers.get(action);
        List<T> ts = new ArrayList<>();
        for (Receiver receiver : list) {
            try {
                ts.add(receiver.receive(carrier));
            } catch (Throwable throwable) {
                log.error(throwable.getMessage(), throwable);
            }
        }
        return ts;
    }
}
